#include "xShader.h"
#include "xTexture.h"
#include "xTechnique.h"



namespace XE
{

	const 	xString xShader::Resource_Type = "Shader";

	xShader::xShader(const xString& name,xResourceHandle handle)
		:xResource(name.c_str(),handle),m_pActiveTech(NULL)
	{
	

	}

	xShader::~xShader()
	{
		DestoryAllTechnique();
		//DestoryParameterMap();
	}


	//void xShader::DestoryParameterMap()
	//{
	//	xShaderParameterMapIterator it = m_ParameterMap.begin();
	//	for(;it!=m_ParameterMap.end();++it)
	//	{
	//		delete it->second;
	//	}

	//	m_ParameterMap.clear();


	//}




	//bool  xShader::HasAutoContantParameter(const xString& SemanticName)
	//{
	//	xAutoConstantParameterVector::iterator it =  m_AutoParameterVector.begin();
	//	for(;it!=m_AutoParameterVector.end();++it)
	//	{
	//		if((*it)->GetSemantic()==SemanticName)
	//			return true;
	//	}
	//	return false;
	//}


/*
	bool  xShader::SetConstantValueBySemantic(const xString& SemanticName,float data )
	{
		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
			   return 	it->second->WriteData(&data,sizeof(float));
			}
		}
		return  false;
	}

	bool xShader::SetConstantValueBySemantic(const xString& SemanticName,int data)
	{
		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
				return 	it->second->WriteData(&data,sizeof(int));
			}
		}
		return  false;

	}

	bool xShader::SetConstantValueBySemantic(const xString& SemanticName, const xMatrix* pData)
	{
		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
				return 	it->second->WriteData(pData,sizeof(xMatrix));
			}
		}
		return  false;

	}

	bool xShader::SetConstantValueBySemantic(const xString& SemanticName,bool  pData)
	{
		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
				return 	it->second->WriteData(&pData,sizeof(bool));
			}
		}
		return  false;

	}

	bool xShader::SetConstantValueBySemantic(const xString& SemanticName,const  xVector3* pData)
	{
		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
				return 	it->second->WriteData(pData,sizeof(xVector3));
			}
		}
		return  false;

	}
	bool xShader::SetConstantValueBySemantic(const xString& SemanticName,const  xColor * pData)
	{
		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
				return 	it->second->WriteData(pData,sizeof(xColor));
			}
		}
		return  false;


	}

	bool xShader::SetConstantValueBySemantic(const xString& SemanticName, const xVector4* pData)
	{
		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
				return 	it->second->WriteData(pData,sizeof(xVector4));
			}
		}
		return  false;


	}

	bool xShader::SetConstantValueBySemantic(const  xString& SemanticName, void* pData,UINT size)
	{
		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
				return 	it->second->WriteData(pData,size);
			}
		}
		return  false;


	}

	bool xShader::SetConstantArrayValueBySemantic(const xString&SemanticName,const float* pData,UINT num)
	{
		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
				return 	it->second->WriteData(pData,sizeof(float)*num);
			}
		}
		return  false;

	}

	bool xShader::SetConstantArrayValueBySemantic(const xString&SemanticName,const int* pData,UINT num)
	{

		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
				return 	it->second->WriteData(pData,sizeof(int)*num);
			}
		}
		return  false;
	}


	bool xShader::SetConstantArrayValueBySemantic(const xString&SemanticName,const bool* pData,UINT num)
	{
		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
				return 	it->second->WriteData(pData,sizeof(bool)*num);
			}
		}
		return  false;

	}

	bool xShader::SetConstantArrayValueBySemantic(const xString&SemanticName, const xMatrix* pData,UINT num)
	{
		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
				return 	it->second->WriteData(pData,sizeof(xMatrix)*num);
			}
		}
		return  false;
	}

	bool xShader::SetConstantArrayValueBySemantic(const xString& SemanticName,const  xVector3* pData,UINT num)
	{
		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
				return 	it->second->WriteData(pData,sizeof(xVector3)*num);
			}
		}
		return  false;

	}


	bool xShader::SetConstantArrayValueBySemantic(const xString& SemanticName,const  xColor * pData,UINT num)
	{
		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
				return 	it->second->WriteData(pData,sizeof(xColor)*num);
			}
		}
		return  false;
	}

	bool xShader::SetConstantArrayValueBySemantic(const xString& SemanticName, const xVector4* pData,UINT num)
	{
		xShaderParameterMapIterator it = m_ParameterMap.begin();
		xShaderParameterMapIterator itend = m_ParameterMap.end();
		for(;it!=itend;++it)
		{
			if(it->second==NULL)
				continue;
			if(it->second->GetSemantic()==SemanticName)
			{
				return 	it->second->WriteData(pData,sizeof(xVector4)*num);
			}
		}
		return  false;
	}





	xShaderParameter*  xShader::GetParameterByName(const xString& name)
	{
		xShaderParameterMapIterator it = m_ParameterMap.find(name);
		if(it==m_ParameterMap.end())
			return NULL;
		return it->second;

	}
*/

	bool xShader::SetConstantValue(const xString& name,float pData)
	{
		//xShaderParameter* pParameter = GetParameterByName(name);
		//if(pParameter==NULL)
		//	return false;
		//return 	pParameter->WriteData(&pData,sizeof(float) );
	   return 	SetConstantValue(name,&pData,sizeof(float));

	}


	//bool xShader::SetConstantValue(const  xString& name, void* pData,UINT size)
	//{

	//	xShaderParameter* pParameter = GetParameterByName(name);
	//	if(pParameter==NULL)
	//		return false;
	//	return 	pParameter->WriteData(pData,size );

	//}


	bool xShader::SetConstantValue(const xString& name,int pData)
	{
		return SetConstantValue(name,&pData,sizeof(int) );
	}


	bool xShader::SetConstantValue(const xString& name,const  xMatrix* pData)
	{
		return SetConstantValue(name,pData,sizeof(xMatrix) );
	}


	bool xShader::SetConstantValue(const xString& name,bool  pData)
	{
		return SetConstantValue(name,&pData,sizeof(bool) );
	}

	bool xShader::SetConstantValue(const xString& name,const  xVector3* pData)
	{
			return SetConstantValue(name,pData,sizeof(xVector3) );
	}

	bool xShader::SetConstantValue(const xString& name,const  xColor * pData)
	{
		return SetConstantValue(name,pData,sizeof(xColor) );
	}



	bool  xShader::SetConstantValue(const xString& name, const xVector4* pData)
	{
			return SetConstantValue(name,pData,sizeof(xVector4) );
	}


	bool xShader::SetConstantArrayValue(const xString&name,const  float* pData,UINT num)
	{
		return SetConstantValue(name,pData,sizeof(float)*num );
	}

	bool xShader::SetConstantArrayValue(const xString&name,const  int* pData,UINT num)
	{
			return SetConstantValue(name,pData,sizeof(UINT)*num );
	}

	bool xShader::SetConstantArrayValue(const xString&name, const bool* pData,UINT num)
	{
			return SetConstantValue(name,pData,sizeof(bool)*num );
	}


	bool xShader::SetConstantArrayValue(const xString&name,const xMatrix* pData,UINT num)
	{
		return SetConstantValue(name,pData,sizeof(xMatrix)*num );
	}



	bool xShader::SetConstantArrayValue(const xString& name,const  xVector3* pData,UINT num)
	{

		return SetConstantValue(name,pData,sizeof(xVector3)*num );

	}
	bool xShader::SetConstantArrayValue(const xString& name,const  xColor * pData,UINT num)
	{
		return SetConstantValue(name,pData,sizeof(xColor)*num );

	}

	bool xShader::SetConstantArrayValue(const xString& name, const xVector4* pData,UINT num)
	{
			return SetConstantValue(name,pData,sizeof(xVector4)*num );
	}



	HRESULT xShader::GetTehcniqueName(UINT index,xString& name) const 
	{
		if(index>m_TechniqueVector.size()-1)
			return X_FAIL;
		name  = m_TechniqueVector.at(index)->GetName();
		return X_OK;

	}

	int   xShader::GetActiveTechniuqeIndex()const
	{
		for(int i = 0;i<m_TechniqueVector.size();++i)
		{
			if(m_TechniqueVector[i]==m_pActiveTech)
				return i;
		}
		return -1;
	}


	bool  xShader::HasTechnique(const xString& name) const 
	{
	
		xTechniqueVector::const_iterator it = m_TechniqueVector.begin();
		xTechniqueVector::const_iterator endit = m_TechniqueVector.end();
		for(;it!=endit	;++it)
		{
			if((*it)==NULL)
				continue;
			if((*it)->GetName()==name)
				return true;
		}
		return false;
	}



	xTechnique* xShader::GetTechnique(UINT index) const 
	{
		if(index>m_TechniqueVector.size()-1)
			return NULL;
		return m_TechniqueVector.at(index);

	}


	xTechnique* xShader::GetTechnique(const  xString& name) const
	{
		xTechniqueVector::const_iterator it = m_TechniqueVector.begin();
		xTechniqueVector::const_iterator endit = m_TechniqueVector.end();
		for(;it!=endit	;++it)
		{
			if((*it)==NULL)
				continue;
			if((*it)->GetName()==name)
				return *it;
		}
		return NULL;

	}

	void xShader::DestoryAllTechnique(void )
	{
		for(size_t i = 0;i<m_TechniqueVector.size();++i)
		{
			SafeDelete( m_TechniqueVector[i])
		}

		m_TechniqueVector.clear();


	}

	bool xShader::DestoryTechnique(const xString& name)
	{
		xTechniqueVector::iterator it = m_TechniqueVector.begin();
		for(;it!=m_TechniqueVector.end();++it)
		{
			if((*it)->GetName()==name)
			{
				delete *it;
			   m_TechniqueVector.erase(it);
			   return true;
			}
		}
		return false;
	}

	bool xShader::DestoryTechnique(xTechnique* pTecheniqe)
	{
		if(pTecheniqe==NULL)
			return false;
		return DestoryTechnique(pTecheniqe->GetName());
	}


	xPass*	 xShader::GetActiveTechniquePass( UINT i)
	{
		if(m_pActiveTech==NULL)
			return NULL;
		return m_pActiveTech->GetPass(i);

	}

	xString  xShader::GetActiveTechniqueName() const 
	{

		if(m_pActiveTech!=NULL)
			return m_pActiveTech->GetName();
		if(m_TechniqueVector.empty())
		{
			xString cc;
			return cc;
		}else
		{
			return m_TechniqueVector.at(0)->GetName();
		}
	}


	xTechnique* xShader::CreateTechnique(const xString& name)
	{
		xTechnique* pTeh =GetTechnique(name);
		if(pTeh!=NULL)
		{
			xLogMessager::getSingleton().logMessage("Create xtehchinque err there are same name tehcnique,name is"+name);
			return NULL;
		}
		pTeh = new xTechnique(name);
		m_TechniqueVector.push_back(pTeh);
		return pTeh;

	}


	//const xString xVertexShader::Resource_Type = "VertexShader";
	//xVertexShader::xVertexShader(const xString& name)
	//	:xShader(name)
	//{

	//}





	//const xString xPixelShader::Resource_Type = "PixelShader";
	//xPixelShader::xPixelShader(const xString& name)
	//	:xShader(name.c_str())
	//{

	//}






















}